extends Node2D
class_name ValidatorController

var pieces:Array[PieceV2]=[]

@onready var piecesNodes:Pieces = get_node("/root/Board_v2/Pieces")


func _ready() -> void:
	GlobalSignals.all_pieces_response_signal.connect(_on_all_pieces_response)


func _on_all_pieces_response(all_pieces:Array[PieceV2]) -> void:
	pieces=all_pieces

## 处理棋子逻辑
func validate_piece(piece:PieceV2,from_pos:Vector2i,tar_pos:Vector2i)->bool:
	var status:bool = false
	match piece.type:
		BoardCommon.TYPE.GENERAL: # 将
			status=generalControl(piece,from_pos,tar_pos)
		BoardCommon.TYPE.ADVISOR: # 士
			status=advisorControl(piece,from_pos,tar_pos)
		BoardCommon.TYPE.CHARIOT: # 车
			GlobalSignals.all_pieces_request_signal.emit()
			status=chariotControl(piece,from_pos,tar_pos,pieces)
		BoardCommon.TYPE.CANNON: # 炮
			GlobalSignals.all_pieces_request_signal.emit()
			status=cannonControl(piece,from_pos,tar_pos,pieces)
		BoardCommon.TYPE.ELEPHANT: # 象
			GlobalSignals.all_pieces_request_signal.emit()
			status=elephantControl(piece,from_pos,tar_pos,pieces)
		BoardCommon.TYPE.HORSE: # 马
			GlobalSignals.all_pieces_request_signal.emit()
			status=horseControl(piece,from_pos,tar_pos,pieces)
		BoardCommon.TYPE.SOLDIER: # 兵
			status=soldierControl(piece,from_pos,tar_pos)
	return status

func advisorControl(piece: PieceV2, from_pos: Vector2i, target_pos: Vector2i) -> bool:
	if piece.type != BoardCommon.TYPE.ADVISOR:
		return false
	
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	# 士只能斜向移动一格
	if abs(dx) != 1 or abs(dy) != 1:
		return false
	
	# 士只能在九宫格内移动
	if not isInPalaceAdvisor(target_pos, piece.side):
		return false
	
	return true

func isInPalaceAdvisor(pos: Vector2i, side: BoardCommon.TURN) -> bool:
	# 红方九宫格（棋盘下方）
	if side == BoardCommon.TURN.RED:
		return pos.x >= 3 and pos.x <= 5 and pos.y >= 0 and pos.y <= 2
	# 黑方九宫格（棋盘上方）
	elif side == BoardCommon.TURN.BLACK:
		return pos.x >= 3 and pos.x <= 5 and pos.y >= 7 and pos.y <= 9
	return false

@warning_ignore("unused_parameter", "shadowed_variable")
func cannonControl(piece: PieceV2, from_pos: Vector2i, target_pos: Vector2i, pieces: Array[PieceV2]) -> bool:
	if piece.type != BoardCommon.TYPE.CANNON:
		return false
	
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	# 炮只能横向或纵向移动，不能斜向移动
	if dx != 0 and dy != 0:
		return false
	
	# 检查移动路径
	var pieces_between = countPiecesBetween(from_pos, target_pos, pieces)
	var target_piece = getPieceAtPosition(target_pos, pieces)
	
	# 移动规则：
	# - 如果目标位置为空，移动路径上不能有任何棋子
	# - 如果目标位置有棋子（吃子），移动路径上必须恰好有一个棋子作为炮架
	if target_piece == null:
		# 移动：路径上不能有棋子
		return pieces_between == 0
	else:
		# 吃子：路径上必须恰好有一个棋子作为炮架，且目标棋子必须是敌方棋子
		return pieces_between == 1 and target_piece.side != piece.side

@warning_ignore("shadowed_variable")
func countPiecesBetween(from_pos: Vector2i, target_pos: Vector2i, pieces: Array[PieceV2]) -> int:
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	# 确定移动方向和步数
	var step_x = 0
	var step_y = 0
	var steps = 0
	
	if dx != 0:  # 横向移动
		step_x = 1 if dx > 0 else -1
		steps = abs(dx)
	else:  # 纵向移动
		step_y = 1 if dy > 0 else -1
		steps = abs(dy)
	
	# 统计路径上的棋子数量（不包括起点和终点）
	var count = 0
	for i in range(1, steps):
		var check_pos = Vector2i(from_pos.x + i * step_x, from_pos.y + i * step_y)
		if isPositionOccupied(check_pos, pieces):
			count += 1
	
	return count

@warning_ignore("shadowed_variable")
func getPieceAtPosition(pos: Vector2i, pieces: Array[PieceV2]) -> PieceV2:
	# 查找在指定位置的棋子
	for p in pieces:
		if p && BoardCommon.pos_to_grid_pos(p.position) == pos:
			return p
	return null

@warning_ignore("shadowed_variable")
func chariotControl(piece: PieceV2, from_pos: Vector2i, target_pos: Vector2i, pieces: Array[PieceV2]) -> bool:
	if piece.type != BoardCommon.TYPE.CHARIOT:
		return false
	
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	# 车只能横向或纵向移动，不能斜向移动
	if dx != 0 and dy != 0:
		return false
	
	# 检查移动路径上是否有其他棋子阻挡
	if isPathBlocked(from_pos, target_pos, pieces):
		return false
	
	return true

@warning_ignore("shadowed_variable")
func isPathBlocked(from_pos: Vector2i, target_pos: Vector2i, pieces: Array[PieceV2]) -> bool:
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	# 确定移动方向和步数
	var step_x = 0
	var step_y = 0
	var steps = 0
	
	if dx != 0:  # 横向移动
		step_x = 1 if dx > 0 else -1
		steps = abs(dx)
	else:  # 纵向移动
		step_y = 1 if dy > 0 else -1
		steps = abs(dy)
	
	# 检查路径上的每个位置（不包括起点和终点）
	for i in range(1, steps):
		var check_pos = Vector2i(from_pos.x + i * step_x, from_pos.y + i * step_y)
		if isPositionOccupied(check_pos, pieces):
			return true  # 路径被阻挡
	
	return false  # 路径畅通
	
@warning_ignore("shadowed_variable")
func elephantControl(piece: PieceV2, from_pos: Vector2i, target_pos: Vector2i, pieces: Array[PieceV2]) -> bool:
	if piece.type != BoardCommon.TYPE.ELEPHANT:
		return false
	
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	# 象走"田"字：必须斜向移动两格
	if abs(dx) != 2 or abs(dy) != 2:
		return false
	
	# 检查是否在己方领地内移动
	if not isInOwnTerritory(target_pos, piece.side):
		return false
	
	# 检查象眼（移动路径中间位置）是否被塞住
	@warning_ignore("integer_division")
	var eye_pos = Vector2i(from_pos.x + dx / 2, from_pos.y + dy / 2)
	if isPositionOccupied(eye_pos, pieces):
		return false
	
	return true

func isInOwnTerritory(pos: Vector2i, side: BoardCommon.TURN) -> bool:
	# 红方（相）只能在己方领地（棋盘下方）
	if side == BoardCommon.TURN.RED:
		return pos.y <= 4  # y坐标0-4为红方领地
	# 黑方（象）只能在己方领地（棋盘上方）
	elif side == BoardCommon.TURN.BLACK:
		return pos.y >= 5  # y坐标5-9为黑方领地
	return false

func generalControl(piece: PieceV2, from_pos: Vector2i, target_pos: Vector2i) -> bool:
	if piece.type != BoardCommon.TYPE.GENERAL:
		return false
	
	var dx = abs(target_pos.x - from_pos.x)
	var dy = abs(target_pos.y - from_pos.y)
	
	# 将只能在九宫格内移动
	if not isInPalaceGeneral(target_pos, piece.side):
		return false
	
	# 将每次只能移动一格，且只能横向或纵向移动
	if (dx == 1 and dy == 0) or (dx == 0 and dy == 1):
		return true
	
	return false

func isInPalaceGeneral(pos: Vector2i, side: BoardCommon.TURN) -> bool:
	# 红方九宫格（棋盘下方）
	if side == BoardCommon.TURN.RED:
		return pos.x >= 3 and pos.x <= 5 and pos.y >= 0 and pos.y <= 2
	# 黑方九宫格（棋盘上方）
	elif side == BoardCommon.TURN.BLACK:
		return pos.x >= 3 and pos.x <= 5 and pos.y >= 7 and pos.y <= 9
	return false

@warning_ignore("shadowed_variable")
func horseControl(piece: PieceV2, from_pos: Vector2i, target_pos: Vector2i, pieces: Array[PieceV2]) -> bool:
	if piece.type != BoardCommon.TYPE.HORSE:
		return false
	
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	# 马的移动必须是"日"字形：一横一竖或一竖一横
	if not ((abs(dx) == 1 and abs(dy) == 2) or (abs(dx) == 2 and abs(dy) == 1)):
		return false
	
	# 检查蹩马腿
	if isHorseBlocked(from_pos, target_pos, pieces):
		return false
	
	return true

@warning_ignore("shadowed_variable")
func isHorseBlocked(from_pos: Vector2i, target_pos: Vector2i, pieces: Array[PieceV2]) -> bool:
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	# 确定蹩马腿的位置
	var block_pos: Vector2i
	
	if abs(dx) == 2 and abs(dy) == 1:  # 横向移动2格，纵向移动1格
		# 蹩马腿在横向中间位置
		@warning_ignore("integer_division")
		block_pos = Vector2i(from_pos.x + dx / 2, from_pos.y)
	elif abs(dx) == 1 and abs(dy) == 2:  # 横向移动1格，纵向移动2格
		# 蹩马腿在纵向中间位置
		@warning_ignore("integer_division")
		block_pos = Vector2i(from_pos.x, from_pos.y + dy / 2)
	else:
		return true  # 无效移动
	
	# 检查蹩马腿位置是否有棋子
	if isPositionOccupied(block_pos, pieces):
		return true  # 马腿被蹩住，不能移动
	
	return false  # 马腿没有被蹩住，可以移动

@warning_ignore("shadowed_variable")
func isPositionOccupied(pos: Vector2i, pieces: Array[PieceV2]) -> bool:
	# 遍历所有棋子，检查是否有棋子在这个位置
	for p in pieces:
		if p && BoardCommon.pos_to_grid_pos(p.position) == pos:
			return true
	return false

func soldierControl(piece:PieceV2,from_pos:Vector2i,target_pos:Vector2i)-> bool:
	if piece.type != BoardCommon.TYPE.SOLDIER: return false
	var dx = target_pos.x - from_pos.x
	var dy = target_pos.y - from_pos.y
	
	if dx == 0 and dy == 0: return false
	
	if piece.side == BoardCommon.TURN.RED:
		if from_pos.y < 5:  # 红方未过河
			return dx == 0 and dy == 1
		else:  # 红方未过河
			return (dx == 0 and dy == 1) or (abs(dx) == 1 and dy == 0)
	if piece.side == BoardCommon.TURN.BLACK:
		if from_pos.y > 4:  # 黑方未过河
			return dx == 0 and dy == -1
		else:  # 黑方已过河
			return (dx == 0 and dy == -1) or (abs(dx) == 1 and dy == 0)
	return false
